// 数组、二维数组

#include<stdio.h>
#include<string.h>
//---------------------------------------------小节分割线--------------------------------------------
// 不同的数组创建类型
//int main()
//{
//    int arr1[10] = { 1,2,3 }; // 1,2,3,0,0,0,0,0,0,0
//    int arr2[] = { 1,2,3,4 }; // 
//    int arr3[5] = { 1,2,3,4,5 };
//    char arr4[3] = { 'a',98, 'c' };
//    char arr5[] = { 'a','b','c' };
//    char arr6[] = "abcdef";
//    return 0;
//}
//---------------小分割线 >.< --------------------
// 一维数组在内存中的存储
// 1.一维数组在内存中是连续存放的
// 2.随着数组下标的增长，元素的地址也在有规律的递增
//int main()
//{
//    int arr[10] = { 0 };
//    int i = 0;
//    int sz = sizeof(arr) / sizeof(arr[0]);
//
//    for (i = 0; i < sz; ++i)
//    {
//        printf("&arr[%d] = %p\n", i, &arr[i]);
//        // %p是按照地址的格式打印，十六进制
//        // 如果用%x打印十六进制，会吞掉前面的0
//        // 打印出来发现每个地址之间相差4个字节
//        // 是因为整型占4个字节
//    }
//    return 0;
//}
//---------------小分割线 >.< --------------------
// 使用指针访问数组的值
// int main()
// {
//     int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//     int i = 0;
//     int sz = sizeof(arr) / sizeof(arr[0]);
//     int* p = arr; // 数组名是数组首元素的地址

//     for (i = 0; i < sz; ++i)
//     {
//         printf("*p = %d\n", *p);
//         printf("p = %p\n", p);
//         p++;
//     }
//     return 0;
// }


// 二维数组
//---------------------------------------------小节分割线--------------------------------------------
// 初始化
//int main()
//{
//	int arr1[3][4] = { 1,2,3,4,5,6,7,8,9,10 }; // 不完全初始化时候，默认补0（整型）或者\0（字符）
//	int arr2[3][4] = { {1,2},{3,4}, {4,5} };
//	int arr3[][4] = { {2,3},{4,5} };//二维数组如果有初始化，行可以省略，列不能省略
//	return 0;
//}
//---------------小分割线 >.< --------------------
// 二维数组的使用
//int main()
//{
//	int arr[3][4] = { 0 };
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 4; j++)
//		{
//			arr[i][j] = i * 4 + j;
//		}
//	}
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 4; j++)
//		{
//			printf("%d\t", arr[i][j]);
//		}
//		printf("\n");
//	}
//	return 0;
//}
//---------------小分割线 >.< --------------------
// 二维数组在内存中的存储
// 二维数组在内存中也是连续存储的
// 这也就是为什么在二维数组定义的时候，可以省略行数，不能省略列数。
// 否则第二行的元素内存中不知道该存储在什么位置
// 由于存储中是顺序存储的，所以arr[0][0]表示的是整个二维数组的首元素地址
// 可以将每一个数组看做一个元素，方便使用指针寻找每一行的首元素位置
// arr[0]可以表示第一个一维数组，也就是第一行的首元素地址
// arr[1]可以表示第二个一维数组，也就是第二行的首元素地址

//int main()
//{
//	int arr[3][4];
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 4; j++)
//		{
//			printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]);
//		}
//	}
//	for (i = 0; i < 3; i++)
//	{
//		int j = 0;
//		for (j = 0; j < 4; j++)
//		{
//			arr[i][j] = i * 4 + j;
//		}
//	}
//	printf("使用指针方式打印二维数组的元素\n");
//	int* p = &arr[0][0];
//	for (int i = 0; i < 12; i++)
//	{
//		printf("%d ", *(p + i));
//	}
//	return 0;
//}
//---------------小分割线 >.< --------------------
// 使用冒泡排序对数组进行排序
//void bubble_sort(int arr[], int sz)
//{
//	for (int i = 0; i < sz - 1; i++)
//	{
//		// 一共排序n-1趟，因为最后一个数就不需要排序了
//		for (int j = 0; j < sz - i - 1; j++)
//		{
//			// 每一趟中需要比较的次数,和当前比较的趟数加起来，就是数组的数量
//			if (arr[j] > arr[j+1])
//			{
//				int tmp = arr[j];
//				arr[j] = arr[j + 1];
//				arr[j + 1] = tmp;
//			}
//		}
//	}
//}
//int main()
//{
//	int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
//	int sz = sizeof(arr) / sizeof(arr[0]);
//	printf("排序前:");
//	for (int i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	printf("\n排序后:");
//	bubble_sort(arr, sz);
//	for (int i = 0; i < sz; i++)
//	{
//		printf("%d ", arr[i]);
//	}
//	return 0;
//}
//---------------小分割线 >.< --------------------
// 数组名是数组首元素的地址
// 但是有两个例外
// 1.sizeof(数组名)，计算整个数组的大小，sizeof内部单独放一个数组名，数组名表示整个数组。
// 2.&数组名，其中数组名表示整个数组，取出的是数组的地址。
int main()
{
    int arr[10] = { 1,2,3,4,5 };
    printf("%p\n", arr);
    printf("%p\n", &arr[0]);
    printf("%d\n", *arr);
    //输出结果
    return 0;
}
